﻿using System;
using System.Collections.Generic;
using Google.OrTools.LinearSolver;
using PPClasses;
using Constraint = Google.OrTools.LinearSolver.Constraint;

namespace PortalPlan_IP
{
    class IntegerProgramming : PPClasses.Solver
    {
        public IntegerProgramming(List<Portal> points) : 
            base(points)
        {
        }

        public override String StatusText()
        {
            return "IP: " + BestScore.Links + " links, " + BestScore.Tris + " fields = " + BestScore.Score +
                       " AP.  " + (Stop ? "Stopped.  " : "") +
                       (CompletelyDone ? "Done.  " : "");
        }

        public override void GoGoGo()
        {
            List<PortalPair> pp = new List<PortalPair>();
            foreach (Pair p in PairChoices)
            {
                pp.Add(new PortalPair() {PortalA = PortalPoints[p.a], PortalB = PortalPoints[p.b]});
            }

            solve(PortalPoints, pp);
            CompletelyDone = true;
        }

        public override bool CanThread
        {
            get { return false; }
        }

        public void solve(List<Portal> portals, List<PortalPair> links)
        {
            Google.OrTools.LinearSolver.Solver solver = Google.OrTools.LinearSolver.Solver.CreateSolver("Portals", "GLPK_MIXED_INTEGER_PROGRAMMING");

            Variable[] X = solver.MakeBoolVarArray(PairChoices.Count);

            for (int i = 0; i < X.Length; i++)
                solver.SetObjectiveCoefficient(X[i], 1);

            for (int idx1=0;idx1<ChoicesBlockNumList.Count;idx1++)
            {
                foreach (int idx2 in ChoicesBlockNumList[idx1])
                {
                    Constraint c = solver.MakeConstraint(0, 1);
                    c.SetCoefficient(X[idx1], 1);
                    c.SetCoefficient(X[idx2], 1);
                }
            }
            solver.TimeLimit();
            solver.SetOptimizationDirection(true);
            solver.Solve();

            List<Pair> pp = new List<Pair>(MustLink);
            for (int i = 0; i < X.Length; i++)
            {
                if (X[i].SolutionValue() > 0.9)
                {
                    pp.Add(PairChoices[i]);
                }
            }

            EvaluateSolution(pp, true);
        }

    }
}